package cn.turboinfo.fuyang.api.gateway.admin.controller.permission;

import cn.turboinfo.fuyang.api.domain.admin.service.permission.PermissionService;
import cn.turboinfo.fuyang.api.entity.admin.pojo.permission.Permission;
import cn.turboinfo.fuyang.api.entity.admin.pojo.permission.PermissionCreator;
import cn.turboinfo.fuyang.api.entity.admin.pojo.permission.PermissionUpdater;
import cn.turboinfo.fuyang.api.entity.admin.pojo.permission.QPermission;
import cn.turboinfo.fuyang.api.gateway.admin.fo.permission.PermissionCreateFO;
import cn.turboinfo.fuyang.api.gateway.admin.fo.permission.PermissionSearchFO;
import cn.turboinfo.fuyang.api.gateway.admin.fo.permission.PermissionUpdateFO;
import cn.turboinfo.fuyang.api.gateway.admin.framework.http.ResponseBodyWrapper;
import cn.turboinfo.fuyang.api.gateway.admin.framework.http.fo.LimitDataFO;
import cn.turboinfo.fuyang.api.gateway.admin.framework.http.fo.LimitFO;
import cn.turboinfo.fuyang.api.gateway.admin.framework.http.fo.SortFO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.request.QSort;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanSearchHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Controller
@ResponseBodyWrapper
@RequestMapping(value = "/admin/permission")
public class PermissionController {

    private final PermissionService permissionService;

    @RequiresPermissions("adminPermission:list")
    @RequestMapping("/list")
    public LimitDataFO<Permission> list(@RequestParam(required = false, defaultValue = "0") Long parentId, @Valid PermissionSearchFO search, LimitFO page, SortFO sort) {
        QRequest request = QBeanSearchHelper.convertQRequest(search)
                // 暂时只列表未限定角色的权限
                .filterEqual(QPermission.roleId, 0L);

        if (sort.getSortFields() == null) {
            sort.setSortFields(new String[]{QPermission.id + "|" + QSort.Order.DESC.name()});
        }

        if (parentId != null && parentId > 0) {
            permissionService.getByIdEnsure(parentId);
            request.filterEqual(QPermission.parentId, parentId);
        } else {
            request.filterEqual(QPermission.parentId, 0L);
        }

        QResponse<Permission> permissionQResponse = permissionService.findAll(request, page.toQPage(sort.toQSortList()));

        return LimitDataFO.fromQResponse(permissionQResponse);
    }

    @RequiresPermissions("adminPermission:list")
    @GetMapping("/ancestors")
    public Collection<Permission> ancestors(@RequestParam(required = false, defaultValue = "0") Long id) {
        if (id == null || id == 0) {
            return null;
        }

        Stack<Permission> stack = new Stack<>();

        Long ancestor = id;
        while (true) {
            Permission permission = permissionService.getByIdEnsure(ancestor);
            stack.push(permission);
            if (permission.getParentId() == 0 || permission.getParentId().equals(permission.getId())) {
                break;
            }
            ancestor = permission.getParentId();
        }
        Collections.reverse(stack);
        return stack;
    }

    @RequiresPermissions("adminPermission:update")
    @PostMapping("/update")
    public Permission update(@RequestBody @Valid PermissionUpdateFO fo) {
        PermissionUpdater.Builder builder = PermissionUpdater.builder(fo.getId());
        QBeanUpdaterHelper.copyPropertiesToUpdateBuilder(builder, PermissionUpdater.class, fo);
        return permissionService.update(builder.build());
    }

    @RequiresPermissions("adminPermission:list")
    @GetMapping("/checkAvailable")
    public boolean checkAvailable(@RequestParam String resource, @RequestParam(required = false, defaultValue = "0") Long id) {
        if (id != null && id > 0) {
            Optional<Permission> permissionOptional = permissionService.getById(id);
            if (permissionOptional.isPresent()) {
                Permission permission = permissionOptional.get();
                if (permission.getResource().equals(resource)) {
                    // 可以维持使用自身的不做变动
                    return true;
                }
            } else {
                return false;
            }
        }
        return permissionService.getByResource(resource).isEmpty();
    }

    @RequiresPermissions("adminPermission:create")
    @PostMapping("/create")
    public Permission create(@RequestBody @Valid PermissionCreateFO fo) {
        PermissionCreator.Builder builder = PermissionCreator.builder();
        QBeanCreatorHelper.copyPropertiesToCreatorBuilder(builder, PermissionCreator.class, fo);
        return permissionService.save(builder.build());
    }

    @RequiresPermissions("adminPermission:delete")
    @PostMapping("/delete")
    public void delete(@RequestParam Long id) {
        Permission permission = permissionService.getByIdEnsure(id);

        List<Permission> permissionList = permissionService.findByParentId(permission.getId());
        if (!permissionList.isEmpty()) {
            throw new RuntimeException("有下级子权限, 不能删除");
        }

        permissionService.deleteById(permission.getId());
    }
}
